<template>
  <a-modal
    v-model:visible="vdata.visible"
    title="快捷收银"
    :footer="null"
    :maskClosable="false"
    @cancel="clear"
  >
    <div class="select-id">
      <div v-if="$access('ENT_MCH_APP_LIST')">
        <p>应用：</p>
        <a-select v-model:value="vdata.appId" style="margin-right: 10px">
          <a-select-option key="">应用AppId</a-select-option>
          <a-select-option
            v-for="item in vdata.mchAppList"
            :key="item.appId"
          >
            {{ item.appName }} [{{ item.appId }}]
          </a-select-option>
        </a-select>
      </div>
      <div>
        <p>门店：</p>
        <a-select v-model:value="vdata.storeId">
          <a-select-option key="">选择门店</a-select-option>
          <a-select-option
            v-for="item in vdata.mchStoreList"
            :key="item.storeId"
          >
            {{ item.storeName }} [{{ item.storeId }}]
          </a-select-option>
        </a-select>
      </div>
    </div>

    <p class="mode">选择收款方式</p>

    <!-- 支付方式 -->
    <div class="boxs">
      <div
        v-for="(item, index) in vdata.imgList"
        :key="item.key"
        class="mode-box"
        :style="{
          borderColor: vdata.imgIndex == index ? item.color : '#e6e6e6'
        }"
        @click="chooseType(index, item.key)"
      >
        <img :src="item.imgSrc" alt="">
        <span>{{ item.text }}</span>
      </div>
    </div>

    <!-- 金额 备注 -->
    <div class="input">
      <span>订单金额：</span>
      <a-input v-model:value="vdata.params.amount" style="width: 100%" />

      <span>备注：</span>
      <a-input v-model:value="vdata.params.remark" />
    </div>

    <!-- 软键盘 -->
    <div class="keyboard display" style="margin-top: 40px">
      <div class="keyboard-num noSelect">
        <div
          v-for="(item, index) in vdata.numList"
          :key="index"
          @click="keyNumber(item)"
        >
          {{ item }}
        </div>
      </div>
      <div class="operate">
        <div class="noSelect" @click="delet">
          <img src="/src/assets/svg/shcnhu.svg" alt="">
        </div>
        <div
          class="reallybutton noSelect"
          style="position: relative"
          @click="openSmallVisible"
        >
          确认支付
        </div>
      </div>
    </div>
  </a-modal>

  <!-- 小弹窗 -->
  <a-modal
    v-model:visible="vdata.SmallVisible"
    :footer="null"
    wrap-class-name="full-modal"
    width="330px"
    :maskClosable="false"
    @cancel="clearSmallModal"
  >
    <div class="modal-body">
      <!-- 扫条码与刷脸 -->
      <div v-if="[1, 2].includes(vdata.imgIndex)" class="code">
        <img
          :src="
            vdata.imgIndex === 1
              ? vdata.imgList[1].imgSrc
              : vdata.imgList[2].imgSrc
          "
          alt=""
        >
        <div
          style="
            margin: 30px 0;
            display: flex;
            flex-direction: column;
            align-items: center;
          "
        >
          <a-input
            ref="barCodeInput"
            v-model:value="vdata.authCode"
            style="margin-bottom: 10px"
            @keyup.enter="handleOk"
          />
          <a-button
            type="primary"
            :loading="vdata.loading"
            @click="handleOk"
          >
            确认支付
          </a-button>
        </div>
      </div>

      <!-- 用户扫聚合码 -->
      <div v-if="vdata.imgIndex === 0">
        <img
          v-if="vdata.apiRes.payData"
          :src="vdata.apiRes.payData"
          alt=""
          style="width: 200px; height: 200px"
        >
        <div class="zfb-wx" style="margin: 10px 0">
          <img src="/src/assets/svg/alipay.svg" alt="">
          <img
            src="/src/assets/svg/wechatpay.svg"
            alt=""
            style="margin: 0 5px"
          >
          <span style="color: grey">支持支付宝与微信支付</span>
        </div>
      </div>

      <!-- 提示文字 来自函数-->
      <p style="font-size: 20px; font-weight: 500; color: grey">
        {{ modeText(vdata.imgIndex) }}
      </p>
      <a-button
        type="primary"
        class="cancel"
        size="large"
        block
        @click="vdata.SmallVisible = false"
      >
        取消收款
      </a-button>
    </div>
  </a-modal>
</template>

<script lang="ts" setup>
import { ref, reactive, getCurrentInstance, nextTick } from 'vue'
import {
  API_URL_MCH_APP,
  API_URL_MCH_STORE_LIST,
  req,
  $payTestOrder
} from '@/api/manage' // 接口
import { $getWebSocketPrefix } from '@/api/manage'
import ReconnectingWebSocket from 'reconnectingwebsocket'
import { message, Modal } from 'ant-design-vue'
// @ts-ignore
import smSvg from '@/assets/svg/sm.svg'
// @ts-ignore
import fkSvg from '@/assets/svg/fk.svg'
// @ts-ignore
import slSvg from '@/assets/svg/sl.svg'

// 获取全局函数
const { $infoBox, $access } =
    getCurrentInstance()!.appContext.config.globalProperties

const vdata: any = reactive({
  currentWayCode: 'QR_CASHIER', // 支付方式
  mchAppList: [] as any, // app列表
  appId: '', // 已选择的appId
  mchStoreList: [] as any, // 门店列表
  storeId: '', // 已选择的门店ID
  loading: false, // 确认收款按钮loading
  visible: false, // 弹出框标识
  SmallVisible: false, // 小弹窗标识
  orderTitle: '快捷收款', // 用于下单传参，写死即可
  payOrderWebSocket: null as any, // 支付订单webSocket对象
  numList: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '0', '00'], //键盘数字集合
  imgIndex: 0, // 付款方式框高亮索引
  authCode: '', // 条码值
  apiRes: '', // 支付信息
  params: {
    // 传参对象
    amount: '',
    remark: ''
  },
  imgList: [
    // 支付方式列表
    {
      imgSrc: smSvg,
      text: '付款主扫',
      color: '#000000',
      key: 'QR_CASHIER'
    },
    {
      imgSrc: fkSvg,
      text: '付款被扫',
      color: '#17c2b2',
      key: 'AUTO_BAR'
    },
    {
      imgSrc: slSvg,
      text: '刷脸支付',
      color: '#4784ff ',
      key: 'AUTO_BAR'
    }
  ]
})

// 获取条码输入框
const barCodeInput = ref()

// 关闭外层弹窗，则清空输入框
const clear = () => (vdata.params.amount = vdata.params.remark = '') // 清空输入框
// 关闭内层
const clearSmallModal = () => {
  vdata.authCode = '' // 清空输入框
  randomOrderNo() // 刷新订单号
}

// 同时关闭内外层弹窗并清空输入框
const closeAllModal = () => {
  vdata.visible = false // 关闭大小弹窗
  vdata.SmallVisible = false // 关闭大小弹窗
  clear()
  clearSmallModal()
}

//  小弹窗提示文字
const modeText = (index) => {
  let text
  switch (index) {
    case 0:
      text = '请扫描付款码收款'
      break
    case 1:
      text = '请扫描二维码收款'
      break
    default:
      text = '请对准摄像头刷脸支付'
  }
  return text
}

//  选择付款方式
const chooseType = (index, key) => {
  vdata.imgIndex = index
  vdata.currentWayCode = key
  randomOrderNo() // 刷新单号
}

// 软键盘点击事件
const keyNumber = (item) => {
  let currentVal = vdata.params.amount
  currentVal == '0' && item != '.' ? (currentVal = item) : (currentVal += item)
  if (!/^(([1-9]{1}\d{0,5})|(0{1}))(\.\d{0,2})?$/.test(currentVal)) return
  vdata.params.amount = currentVal
}

//  删除按钮
const delet = () => {
  let currentVal = vdata.params.amount
  !currentVal || currentVal.length <= 1
      ? (vdata.params.amount = '')
      : (vdata.params.amount = vdata.params.amount.substring(
          0,
          currentVal.length - 1
      ))
}

//  订单号
const randomOrderNo = () => {
  vdata.mchOrderNo =
      'M' +
      new Date().getTime() +
      Math.floor(Math.random() * (9999 - 1000) + 1000)
}

// 开启小弹窗 包含前置校验
const openSmallVisible = () => {
  // 判断支付金额是否为0
  if (!vdata.params.amount || vdata.params.amount == 0.0)
    return $infoBox.message.error('请输入支付金额')

  // 判断是否选择应用
  if (vdata.appId === '' && $access('ENT_MCH_APP_LIST'))
    return $infoBox.message.error('请选择一个应用')

  // 判断是否选择门店
  if (vdata.storeId === '') return $infoBox.message.error('请选择一个门店')

  // 验证金额是否合法
  if (!/^(([1-9]{1}\d{0,5})|(0{1}))(\.\d{0,2})?$/.test(vdata.params.amount))
    return $infoBox.message.error('请输入合法金额')

  vdata.SmallVisible = true // 开启弹窗

  nextTick(() => {
    // 弹窗展示后，输入框默认展示焦点
    if (barCodeInput.value) barCodeInput.value.focus()
  })

  // 如果是聚合码支付 则直接吊起下单
  if (vdata.currentWayCode == 'QR_CASHIER') reallyPay()
}

//  确认收款 下单
const reallyPay = () => {
  vdata.loading = true
  $payTestOrder({
    wayCode: vdata.currentWayCode, // 支付方式
    amount: vdata.params.amount, // 支付金额
    appId: vdata.appId, // appId
    storeId: vdata.storeId, // storeId
    mchOrderNo: vdata.mchOrderNo, // 订单编号
    payDataType: 'codeImgUrl', // 支付参数（二维码，条码）快捷收银都是走聚合支付
    authCode: vdata.authCode, // 条码值
    divisionMode: 0, // 分账模式 0代表不分账 快捷收银写死即可
    orderTitle: vdata.orderTitle // 订单标题
  })
      .then((res) => {
        vdata.apiRes = res
        if (vdata.payOrderWebSocket) vdata.payOrderWebSocket.close() // 关闭上一个webSocket监听

        // 此处判断接口中返回的orderState，值为0，1 代表支付中，直接放行无需处理，2 成功 3 失败
        if (res.orderState === 2 || res.orderState === 3) {
          if (res.orderState === 2) {
            handleClose()
            const succModal = Modal.success({
              title: '支付成功',
              content: '2秒后自动关闭'
            })
            closeAllModal()
            setTimeout(() => {
              succModal.destroy()
            }, 2000)
          } else if (res.orderState === 3) {
            handleClose()
            Modal.error({
              title: '支付失败',
              content: `错误码：${res.errCode}`
            })
          }
          vdata.loading = false
          return
        }

        // 监听响应结果
        // @ts-ignore
        vdata.payOrderWebSocket = new ReconnectingWebSocket(
            $getWebSocketPrefix() +
            '/api/anon/ws/payOrder/' +
            res.payOrderId +
            '/' +
            new Date().getTime()
        )
        vdata.payOrderWebSocket.onopen = () => {}
        vdata.payOrderWebSocket.onmessage = (msgObject) => {
          const resMsgObject = JSON.parse(msgObject.data)
          if (resMsgObject.state === 2) {
            handleClose()
            const succModal = Modal.success({
              title: '支付成功',
              content: '2秒后自动关闭'
            })
            closeAllModal()
            setTimeout(() => {
              succModal.destroy()
            }, 2000)
          } else {
            handleClose()
            Modal.error({
              title: '支付失败',
              content: `错误码：${res.errCode}`
            })
          }
        }
        vdata.loading = false
        randomOrderNo() // 刷新订单号
      })
      .catch(() => {
        vdata.loading = false
        randomOrderNo() // 刷新订单号
      })
}

// 打开弹窗时请求应用列表与门店列表
const getList = () => {
  // 是否有应用的权限
  if ($access('ENT_MCH_APP_LIST')) {
    // 请求接口，获取所有的appid，只有此处进行pageSize=-1传参
    req.list(API_URL_MCH_APP, { pageSize: -1 }).then((res) => {
      vdata.mchAppList = res.records
      // 赋值默认值
      if (vdata.mchAppList.length > 0) {
        vdata.appId = vdata.mchAppList[0].appId
      }
    })
  } else {
    vdata.appId = '' // 没有权限就传空
  }

  // 请求接口，获取商户所有门店，只有次数进行pageSize=-1传参
  req.list(API_URL_MCH_STORE_LIST, { pageSize: -1 }).then((res) => {
    vdata.mchStoreList = res.records
    if (vdata.mchStoreList.length > 0) {
      vdata.storeId = vdata.mchStoreList[0].storeId // 赋予默认值
    }
  })

  // 在进入页面时刷新订单号
  randomOrderNo()
}

//  扫条码与刷脸确认按钮， 输入框输入内容后自动调用
function handleOk() {
  if (!vdata.authCode) return
  reallyPay() // 调起下单接口
}

//  清除WebSocket
function handleClose() {
  if (vdata.payOrderWebSocket) {
    vdata.payOrderWebSocket.close()
  }
}

// 开启弹窗，供父组件调用
const showModal = () => {
  vdata.visible = true
  getList()
}

defineExpose({ showModal })

// 监听键盘事件
document.addEventListener('keydown', (e) => {
  // 大弹窗开启，并且小弹窗未开启的情况下，回车掉起支付按钮
  if (vdata.visible && !vdata.SmallVisible && e.keyCode === 13)
    openSmallVisible()
  // f1 f2 f3 快捷切换支付方式 (112 113 114)
})
</script>
<style lang="less">
.mode {
  text-align: center;
  font-size: 16px;
  color: #000;
  margin: 16px 0;
}
.boxs {
  margin-bottom: 10px;
  display: flex;
  justify-content: space-between;
  .mode-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px solid #e6e6e6;
    border-radius: 10px;
    box-sizing: border-box;
    width: 96px;
    height: 96px;
    span {
      margin-top: 10px;
    }
  }
}
.input {
  span {
    display: inline-block;
    margin: 20px 0 10px 0;
  }
}
// 键盘
.keyboard {
  display: flex;
  width: 100%;
  // background: #0b6159;
  // margin-top: 11px;
  box-sizing: border-box;
  // padding: 3PX;
  .keyboard-num {
    display: flex;
    flex-flow: row wrap;
    flex-grow: 1;
    justify-content: flex-start;
    align-items: center;
    div {
      width: 33%;
      height: 60px;
      background: var(--ant-primary-color);
      font-size: 22px;
      font-weight: 700;
      text-align: center;
      color: #ffffff;
      line-height: 60px;
      border: 2px solid #fff;
      box-sizing: border-box;
      user-select: none;
      border-radius: 5px;
      &:hover {
        cursor: pointer;
      }
      &:active {
        opacity: 0.8;
      }
    }
  }

  .operate {
    width: 25%;
    margin-right: 1px;
    user-select: none;
    div:nth-child(1) {
      width: 100%;
      height: 61px;
      background: var(--ant-primary-color);
      border: 2px solid #fff;
      box-sizing: border-box;
      border-radius: 5px;
      &:active {
        opacity: 0.8;
      }
      img {
        width: 20px;
        height: 14px;
        margin: 23px 65px;
      }
    }
    div:nth-child(2) {
      width: 100%;
      border-radius: 5px;
      height: 182px;
      background: #ffb22d;
      border-radius: 0px 0px 5px 0px;
      line-height: 184px;
      font-size: 22px;
      font-family: PingFang SC, PingFang SC-Bold;
      font-weight: 700;
      text-align: center;
      color: #ffffff;
      border: 2px solid #fff;
      box-sizing: border-box;
      &:active {
        opacity: 0.8;
      }
    }
  }
}

.noSelect {
  display: flex;
  align-items: center;
  justify-content: center;
  &:hover {
    cursor: pointer;
  }
}

// 小弹窗样式
.full-modal {
  .ant-modal {
    top: 50%;
    padding-bottom: 0;
    margin: 0 auto;
    margin-top: -200px;
  }
  .ant-modal-content {
    display: flex;
    flex-direction: column;
    height: 400px;
  }
}
.modal-body {
  width: 282px;
  height: 352px;
  display: flex;
  position: relative;
  padding: 24px;
  left: 0;
  top: 0;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  .code {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    img {
      width: 50px;
      height: 50px;
      margin: 0 auto;
    }
    .auth-code {
      display: flex;
      justify-content: space-between;
    }
  }
}
.cancel {
  position: absolute;
  bottom: 0;
  left: 0;
  // left: 50%;
  // margin-left: -50px;
}
.select-id {
  display: flex;
  justify-content: space-between;
  & > div {
    display: flex;
    flex-direction: column;
    width: 45%;
    flex-grow: 1;
    p {
      margin-bottom: 10px;
    }
  }
}
</style>
